bitkeeper revision 1.1159.82.1 (4152d2abNRTmjgcJM5fkbYQyAoi9pA)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 23 Sep 2004 13:42:03 +0000 (13:42 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Thu, 23 Sep 2004 13:42:03 +0000 (13:42 +0000)
Change device messaging to support adding netifs at runtime,
and to support front-end polling.

12 files changed:
linux-2.6.8.1-xen-sparse/drivers/xen/blkback/control.c
linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c
linux-2.6.8.1-xen-sparse/drivers/xen/netback/control.c
linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c
tools/python/xen/lowlevel/xu/xu.c
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/blkif.py
tools/python/xen/xend/server/controller.py
tools/python/xen/xend/server/messages.py
tools/python/xen/xend/server/netif.py
xen/include/hypervisor-ifs/io/domain_controller.h

index 0b2622465170313abbbe7de56581fb49e01e225a..b55bae7b1fe69dc6c69f5d19aaa21f066375dd99 100644 (file)
@@ -71,16 +71,16 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 
 void blkif_ctrlif_init(void)
 {
-    ctrl_msg_t                       cmsg;
-    blkif_be_driver_status_changed_t st;
+    ctrl_msg_t cmsg;
+    blkif_be_driver_status_t st;
 
     (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
                                     CALLBACK_IN_BLOCKING_CONTEXT);
 
     /* Send a driver-UP notification to the domain controller. */
     cmsg.type      = CMSG_BLKIF_BE;
-    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(blkif_be_driver_status_changed_t);
+    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_be_driver_status_t);
     st.status      = BLKIF_DRIVER_STATUS_UP;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
index 259275ebd13d69648e8ca62e5291efec05a0fa82..e282c1e2458e5b2c2501b7da4ab5a8c482fa4fc5 100644 (file)
@@ -1010,23 +1010,23 @@ void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp)
 }
 
 
-static void blkif_status_change(blkif_fe_interface_status_changed_t *status)
+static void blkif_status_change(blkif_fe_interface_status_t *status)
 {
     ctrl_msg_t                   cmsg;
     blkif_fe_interface_connect_t up;
     long rc;
 
-    if ( status->handle != 0 )
-    {
-        printk(KERN_WARNING "Status change on unsupported blkif %d\n",
-               status->handle);
-        return;
-    }
+/*     if ( status->handle != 0 ) */
+/*     { */
+/*         printk(KERN_WARNING "Status change on unsupported blkif %d\n", */
+/*                status->handle); */
+/*         return; */
+/*     } */
 
     switch ( status->status )
     {
-    case BLKIF_INTERFACE_STATUS_DESTROYED:
-        printk(KERN_WARNING "Unexpected blkif-DESTROYED message in state %d\n",
+    case BLKIF_INTERFACE_STATUS_CLOSED:
+        printk(KERN_WARNING "Unexpected blkif-CLOSED message in state %d\n",
                blkif_state);
         break;
 
@@ -1148,11 +1148,11 @@ static void blkif_status_change(blkif_fe_interface_status_changed_t *status)
 
         break;
 
-    case BLKIF_INTERFACE_STATUS_CHANGED:
-        /* The domain controller is notifying us that a device has been
-        * added or removed.
-        */
-        break;
+//    case BLKIF_INTERFACE_STATUS_CHANGED:
+//        /* The domain controller is notifying us that a device has been
+//        * added or removed.
+//        */
+//        break;
 
     default:
         printk(KERN_WARNING "Status change to unknown value %d\n", 
@@ -1166,14 +1166,14 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 {
     switch ( msg->subtype )
     {
-    case CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
-        if ( msg->length != sizeof(blkif_fe_interface_status_changed_t) )
+    case CMSG_BLKIF_FE_INTERFACE_STATUS:
+        if ( msg->length != sizeof(blkif_fe_interface_status_t) )
             goto parse_error;
-        blkif_status_change((blkif_fe_interface_status_changed_t *)
+        blkif_status_change((blkif_fe_interface_status_t *)
                             &msg->msg[0]);
         break;        
 #if 0
-    case CMSG_BLKIF_FE_VBD_STATUS_CHANGED:
+    case CMSG_BLKIF_FE_VBD_STATUS:
         update_tq.routine = update_vbds_task;
         schedule_task(&update_tq);
         break;
@@ -1194,7 +1194,7 @@ static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 int __init xlblk_init(void)
 {
     ctrl_msg_t                       cmsg;
-    blkif_fe_driver_status_changed_t st;
+    blkif_fe_driver_status_t st;
     int i;
     
     if ( (start_info.flags & SIF_INITDOMAIN) 
@@ -1215,8 +1215,8 @@ int __init xlblk_init(void)
 
     /* Send a driver-UP notification to the domain controller. */
     cmsg.type      = CMSG_BLKIF_FE;
-    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(blkif_fe_driver_status_changed_t);
+    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_fe_driver_status_t);
     st.status      = BLKIF_DRIVER_STATUS_UP;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
@@ -1245,12 +1245,12 @@ void blkdev_suspend(void)
 void blkdev_resume(void)
 {
     ctrl_msg_t                       cmsg;
-    blkif_fe_driver_status_changed_t st;    
+    blkif_fe_driver_status_t st;    
 
     /* Send a driver-UP notification to the domain controller. */
     cmsg.type      = CMSG_BLKIF_FE;
-    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(blkif_fe_driver_status_changed_t);
+    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
+    cmsg.length    = sizeof(blkif_fe_driver_status_t);
     st.status      = BLKIF_DRIVER_STATUS_UP;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
index cf1b07503100d7f352538b6a7869b5bacf9a0ac7..6ca0ba2c7585f67683f3986db9d48f0968beb2d1 100644 (file)
@@ -49,16 +49,16 @@ static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 
 void netif_ctrlif_init(void)
 {
-    ctrl_msg_t                       cmsg;
-    netif_be_driver_status_changed_t st;
+    ctrl_msg_t cmsg;
+    netif_be_driver_status_t st;
 
     (void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx,
                                     CALLBACK_IN_BLOCKING_CONTEXT);
 
     /* Send a driver-UP notification to the domain controller. */
     cmsg.type      = CMSG_NETIF_BE;
-    cmsg.subtype   = CMSG_NETIF_BE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(netif_be_driver_status_changed_t);
+    cmsg.subtype   = CMSG_NETIF_BE_DRIVER_STATUS;
+    cmsg.length    = sizeof(netif_be_driver_status_t);
     st.status      = NETIF_DRIVER_STATUS_UP;
     memcpy(cmsg.msg, &st, sizeof(st));
     ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
index f04c6a1b59913850cd9593caac367a4b019306c7..485d23b8d18d980a239f4cb8f9957ff5da734cb6 100644 (file)
 #include <net/arp.h>
 #include <net/route.h>
 
-#if 0
+#define DEBUG 0
+
+#if DEBUG
+
 #define DPRINTK(fmt, args...) \
     printk(KERN_INFO "[XEN] %s" fmt, __FUNCTION__, ##args)
+
 #else
+
 #define DPRINTK(fmt, args...) ((void)0)
+
 #endif
 
+#define IPRINTK(fmt, args...) \
+    printk(KERN_INFO "[XEN]" fmt, ##args)
+
+#define WPRINTK(fmt, args...) \
+    printk(KERN_WARNING "[XEN]" fmt, ##args)
+
+#define EPRINTK(fmt, args...) \
+    printk(KERN_ERROR "[XEN]" fmt, ##args)
+
+
+
 #ifndef __GFP_NOWARN
 #define __GFP_NOWARN 0
 #endif
@@ -101,6 +118,24 @@ struct net_private
     struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
 };
 
+static char * status_name[] = {
+    [NETIF_INTERFACE_STATUS_CLOSED]       = "closed",
+    [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
+    [NETIF_INTERFACE_STATUS_CONNECTED]    = "connected",
+    [NETIF_INTERFACE_STATUS_CHANGED]      = "changed",
+};
+
+static char * be_state_name[] = {
+    [BEST_CLOSED]       = "closed",
+    [BEST_DISCONNECTED] = "disconnected",
+    [BEST_CONNECTED]    = "connected",
+};
+
+static char * user_state_name[] = {
+    [UST_CLOSED] = "closed",
+    [UST_OPEN]   = "open",
+};
+
 /* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
 #define ADD_ID_TO_FREELIST(_list, _id)             \
     (_list)[(_id)] = (_list)[0];                   \
@@ -131,6 +166,7 @@ struct netif_ctrl {
     int connected_n;
     /** Error code. */
     int err;
+    int up;
 };
 
 static struct netif_ctrl netctrl;
@@ -138,15 +174,16 @@ static struct netif_ctrl netctrl;
 static void netctrl_init(void)
 {
     memset(&netctrl, 0, sizeof(netctrl));
-    netctrl.interface_n = -1;
+    netctrl.up = NETIF_DRIVER_STATUS_DOWN;
 }
 
 /** Get or set a network interface error.
  */
 static int netctrl_err(int err)
 {
-    if ( (err < 0) && !netctrl.err )
+    if ( (err < 0) && !netctrl.err ){
         netctrl.err = err;
+    }
     return netctrl.err;
 }
 
@@ -157,8 +194,12 @@ static int netctrl_err(int err)
 static int netctrl_connected(void)
 {
     int ok = 0;
-    ok = (netctrl.err ? netctrl.err :
-          (netctrl.connected_n == netctrl.interface_n));
+
+    if(netctrl.err){
+        ok = netctrl.err;
+    } else if(netctrl.up == NETIF_DRIVER_STATUS_UP){
+        ok = (netctrl.connected_n == netctrl.interface_n);
+    }
     return ok;
 }
 
@@ -175,11 +216,11 @@ static int netctrl_connected_count(void)
 
     connected = 0;
     
-    list_for_each(ent, &dev_list)
-    {
+    list_for_each(ent, &dev_list) {
         np = list_entry(ent, struct net_private, list);
-        if ( np->backend_state == BEST_CONNECTED )
+        if (np->backend_state == BEST_CONNECTED){
             connected++;
+        }
     }
 
     netctrl.connected_n = connected;
@@ -589,7 +630,7 @@ static struct net_device_stats *network_get_stats(struct net_device *dev)
 
 
 static void network_connect(struct net_device *dev,
-                            netif_fe_interface_status_changed_t *status)
+                            netif_fe_interface_status_t *status)
 {
     struct net_private *np;
     int i, requeue_idx;
@@ -647,8 +688,8 @@ static void network_connect(struct net_device *dev,
     wmb();                
     np->rx->req_prod = requeue_idx;
 
-printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n",
-       np->tx->req_prod,np->rx->req_prod);
+    printk(KERN_ALERT "[XEN] Netfront recovered tx=%d rxfree=%d\n",
+           np->tx->req_prod,np->rx->req_prod);
 
 
     /* Step 3: All public and private state should now be sane.  Get
@@ -668,130 +709,155 @@ printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n",
     spin_unlock_irq(&np->rx_lock);
 }
 
-static void netif_status_change(netif_fe_interface_status_changed_t *status)
-{
-    ctrl_msg_t                   cmsg;
-    netif_fe_interface_connect_t up;
-    struct net_device *dev;
-    struct net_private *np;
-    
-    DPRINTK(">\n");
-    DPRINTK("> status=%d handle=%d mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
-           status->status,
-           status->handle,
-           status->mac[0], status->mac[1], status->mac[2],
-           status->mac[3], status->mac[4], status->mac[5]);
-
-    if ( netctrl.interface_n <= 0 )
-    {
-        printk(KERN_WARNING "Status change: no interfaces\n");
-        return;
+static void vif_show(struct net_private *np){
+#if DEBUG
+    if(np){
+        IPRINTK(" <vif handle=%u %s(%s) evtchn=%u irq=%u tx=%p rx=%p>\n",
+               np->handle,
+               be_state_name[np->backend_state],
+               user_state_name[np->user_state],
+               np->evtchn,
+               np->irq,
+               np->tx,
+               np->rx);
+    } else {
+        IPRINTK("<vif NULL>\n");
     }
+#endif
+}
 
-    dev = find_dev_by_handle(status->handle);
-    if(!dev){
-        printk(KERN_WARNING "Status change: invalid netif handle %u\n",
-               status->handle);
-         return;
-    }
-    np  = dev->priv;
-    
-    switch ( status->status )
-    {
-    case NETIF_INTERFACE_STATUS_DESTROYED:
-        printk(KERN_WARNING "Unexpected netif-DESTROYED message in state %d\n",
-               np->backend_state);
-        break;
+/* Send a connect message to xend to tell it to bring up the interface.
+ */
+static void send_interface_connect(struct net_private *np){
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
+        .length  = sizeof(netif_fe_interface_connect_t),
+    };
+    netif_fe_interface_connect_t *msg = (void*)cmsg.msg;
+
+    DPRINTK(">\n"); vif_show(np); 
+    msg->handle = np->handle;
+    msg->tx_shmem_frame = (virt_to_machine(np->tx) >> PAGE_SHIFT);
+    msg->rx_shmem_frame = (virt_to_machine(np->rx) >> PAGE_SHIFT);
+        
+    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+    DPRINTK("<\n");
+}
 
-    case NETIF_INTERFACE_STATUS_DISCONNECTED:
-        if ( np->backend_state != BEST_CLOSED )
-        {
-            printk(KERN_WARNING "Unexpected netif-DISCONNECTED message"
-                   " in state %d\n", np->backend_state);
-           printk(KERN_INFO "Attempting to reconnect network interface\n");
-
-            /* Begin interface recovery.
-            *
-            * NB. Whilst we're recovering, we turn the carrier state off.  We
-            * take measures to ensure that this device isn't used for
-            * anything.  We also stop the queue for this device.  Various
-            * different approaches (e.g. continuing to buffer packets) have
-            * been tested but don't appear to improve the overall impact on
-             * TCP connections.
-            *
-             * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
-             * is initiated by a special "RESET" message - disconnect could
-             * just mean we're not allowed to use this interface any more.
-             */
-
-            /* Stop old i/f to prevent errors whilst we rebuild the state. */
-            spin_lock_irq(&np->tx_lock);
-            spin_lock(&np->rx_lock);
-            netif_stop_queue(dev);
-            np->backend_state = BEST_DISCONNECTED;
-            spin_unlock(&np->rx_lock);
-            spin_unlock_irq(&np->tx_lock);
-
-            /* Free resources. */
-            free_irq(np->irq, dev);
-            unbind_evtchn_from_irq(np->evtchn);
-           free_page((unsigned long)np->tx);
-            free_page((unsigned long)np->rx);
-        }
+/* Send a driver status notification to the domain controller. */
+static int send_driver_status(int ok)
+{
+    int err = 0;
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
+        .length  = sizeof(netif_fe_driver_status_t),
+    };
+    netif_fe_driver_status_t *msg = (void*)cmsg.msg;
+
+    msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN);
+    err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+    return err;
+}
 
-        /* Move from CLOSED to DISCONNECTED state. */
-        np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
-        np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
-        memset(np->tx, 0, PAGE_SIZE);
-        memset(np->rx, 0, PAGE_SIZE);
-        np->backend_state = BEST_DISCONNECTED;
-
-        /* Construct an interface-CONNECT message for the domain controller. */
-        cmsg.type      = CMSG_NETIF_FE;
-        cmsg.subtype   = CMSG_NETIF_FE_INTERFACE_CONNECT;
-        cmsg.length    = sizeof(netif_fe_interface_connect_t);
-        up.handle      = status->handle;
-        up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
-        up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
-        memcpy(cmsg.msg, &up, sizeof(up));
-        
-        /* Tell the controller to bring up the interface. */
-        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-        break;
+/* Stop network device and free tx/rx queues and irq.
+ */
+static void vif_release(struct net_private *np){
 
-    case NETIF_INTERFACE_STATUS_CONNECTED:
-        if ( np->backend_state == BEST_CLOSED )
-        {
-            printk(KERN_WARNING "Unexpected netif-CONNECTED message"
-                   " in state %d\n", np->backend_state);
-            break;
-        }
+    /* Stop old i/f to prevent errors whilst we rebuild the state. */
+    spin_lock_irq(&np->tx_lock);
+    spin_lock(&np->rx_lock);
+    netif_stop_queue(np->dev);
+    //np->backend_state = BEST_DISCONNECTED;
+    spin_unlock(&np->rx_lock);
+    spin_unlock_irq(&np->tx_lock);
+    
+    /* Free resources. */
+    if(np->tx != NULL){
+        free_irq(np->irq, np->dev);
+        unbind_evtchn_from_irq(np->evtchn);
+        free_page((unsigned long)np->tx);
+        free_page((unsigned long)np->rx);
+        np->irq = 0;
+        np->evtchn = 0;
+        np->tx = NULL;
+        np->rx = NULL;
+    }
 
-        memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+}
 
-        network_connect(dev, status);
+/* Release vif resources and close it down completely.
+ */
+static void vif_close(struct net_private *np){
+    DPRINTK(">\n"); vif_show(np);
+    WPRINTK(" Unexpected netif-CLOSED message in state %s\n",
+            be_state_name[np->backend_state]);
+    vif_release(np);
+    np->backend_state = BEST_CLOSED;
+    //todo: take dev down and free.
+    vif_show(np); DPRINTK("<\n");
+}
 
-        np->evtchn = status->evtchn;
-        np->irq = bind_evtchn_to_irq(np->evtchn);
-        (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, 
-                          dev->name, dev);
-        netctrl_connected_count();
-        vif_wake(dev);
-        break;
+/* Move the vif into disconnected state.
+ * Allocates tx/rx pages.
+ * Sends connect message to xend.
+ */
+static void vif_disconnect(struct net_private *np){
+    DPRINTK(">\n");
+    if(np->tx) free_page((unsigned long)np->tx);
+    if(np->rx) free_page((unsigned long)np->rx);
+    // Before this np->tx and np->rx had better be null.
+    np->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
+    np->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
+    memset(np->tx, 0, PAGE_SIZE);
+    memset(np->rx, 0, PAGE_SIZE);
+    np->backend_state = BEST_DISCONNECTED;
+    send_interface_connect(np);
+    vif_show(np); DPRINTK("<\n");
+}
 
-    case NETIF_INTERFACE_STATUS_CHANGED:
-        /* The domain controller is notifying us that a device has been
-        * added or removed.
-        */
-        break;
+/* Begin interface recovery.
+ *
+ * NB. Whilst we're recovering, we turn the carrier state off.  We
+ * take measures to ensure that this device isn't used for
+ * anything.  We also stop the queue for this device.  Various
+ * different approaches (e.g. continuing to buffer packets) have
+ * been tested but don't appear to improve the overall impact on
+ * TCP connections.
+ *
+ * TODO: (MAW) Change the Xend<->Guest protocol so that a recovery
+ * is initiated by a special "RESET" message - disconnect could
+ * just mean we're not allowed to use this interface any more.
+ */
+static void vif_reset(struct net_private *np){
+    DPRINTK(">\n");
+    IPRINTK(" Attempting to reconnect network interface: handle=%u\n",
+            np->handle);
+    
+    vif_release(np);
+    vif_disconnect(np);
+    vif_show(np); DPRINTK("<\n");
+}
 
-    default:
-        printk(KERN_WARNING "Status change to unknown value %d\n", 
-               status->status);
-        break;
-    }
+/* Move the vif into connected state.
+ * Sets the mac and event channel from the message.
+ * Binds the irq to the event channel.
+ */
+static void vif_connect(struct net_private *np, netif_fe_interface_status_t *status){
+    struct net_device *dev = np->dev;
+    DPRINTK(">\n");
+    memcpy(dev->dev_addr, status->mac, ETH_ALEN);
+    network_connect(dev, status);
+    np->evtchn = status->evtchn;
+    np->irq = bind_evtchn_to_irq(np->evtchn);
+    (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
+    netctrl_connected_count();
+    vif_wake(dev);
+    vif_show(np); DPRINTK("<\n");
 }
 
+
 /** Create a network device.
  * @param handle device handle
  * @param val return parameter for created device
@@ -819,10 +885,12 @@ static int create_netdev(int handle, struct net_device **val)
     spin_lock_init(&np->rx_lock);
 
     /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */
-    for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ )
+    for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ ){
         np->tx_skbs[i] = (void *)(i+1);
-    for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ )
+    }
+    for ( i = 0; i <= NETIF_RX_RING_SIZE; i++ ){
         np->rx_skbs[i] = (void *)(i+1);
+    }
 
     dev->open            = network_open;
     dev->hard_start_xmit = network_start_xmit;
@@ -840,58 +908,172 @@ static int create_netdev(int handle, struct net_device **val)
     list_add(&np->list, &dev_list);
 
   exit:
-    if ( (err != 0) && (dev != NULL ) )
+    if ( (err != 0) && (dev != NULL ) ){
         kfree(dev);
-    else if ( val != NULL )
+    } else if ( val != NULL ) {
         *val = dev;
+    }
     return err;
 }
 
-/*
- * Initialize the network control interface. Set the number of network devices
- * and create them.
+/* Get the target interface for a status message.
+ * Creates the interface when it makes sense.
+ * The returned interface may be null when there is no error.
+ *
+ * @param status status message
+ * @param np return parameter for interface state
+ * @return 0 on success, error code otherwise
  */
+static int target_vif(netif_fe_interface_status_t *status, struct net_private **np)
+{
+    int err = 0;
+    struct net_device *dev;
 
-static void netif_driver_status_change(
-    netif_fe_driver_status_changed_t *status)
+    DPRINTK("> handle=%d\n", status->handle);
+    if(status->handle < 0) {
+        err = -EINVAL;
+        goto exit;
+    }
+    dev = find_dev_by_handle(status->handle);
+    DPRINTK("> dev=%p\n", dev);
+    if(dev) goto exit;
+    // No good - give up.
+    if(status->status == NETIF_INTERFACE_STATUS_CLOSED) goto exit;
+    if(status->status == NETIF_INTERFACE_STATUS_CHANGED) goto exit;
+    // It's a new interface in a good state - create it.
+    DPRINTK("> create device...\n");
+    err = create_netdev(status->handle, &dev);
+    if(err) goto exit;
+    netctrl.interface_n++;
+  exit:
+    if(np){
+        *np = ((dev && !err) ? dev->priv : NULL);
+    }
+    DPRINTK("< err=%d\n", err);
+    return err;
+}
+
+/* Warn about an unexpected status. */
+static void unexpected(struct net_private *np,
+                       netif_fe_interface_status_t *status)
+{
+    WPRINTK(" Unexpected netif status %s in state %s\n",
+            status_name[status->status],
+            be_state_name[np->backend_state]);
+}
+
+/* Handle an interface status message. */
+static void netif_interface_status(netif_fe_interface_status_t *status)
 {
     int err = 0;
-    int i;
+    struct net_private *np = NULL;
+    
+    DPRINTK(">\n");
+    DPRINTK("> status=%s handle=%d\n", status_name[status->status], status->handle);
 
-    DPRINTK("> max_handle=%d\n", status->max_handle);
+    err = target_vif(status, &np);
+    if(err){
+        WPRINTK(" Invalid netif: handle=%u\n", status->handle);
+        return;
+    }
+    if(np == NULL){
+        DPRINTK("> no vif\n");
+        return;
+    }
 
-    /* XXX FIXME: Abuse of 'max_handle' as interface count. */
-    netctrl.interface_n = status->max_handle;
-    netctrl.connected_n = 0;
+    DPRINTK(">\n"); vif_show(np);
 
-    for ( i = 0; i < netctrl.interface_n; i++ )
-    {
-        if ( (err = create_netdev(i, NULL)) != 0 )
-        {
-            netctrl_err(err);
+    switch (status->status) {
+
+    case NETIF_INTERFACE_STATUS_CLOSED:
+        switch(np->backend_state){
+
+        case BEST_CLOSED:
+        case BEST_DISCONNECTED:
+        case BEST_CONNECTED:
+            vif_close(np);
+            break;
+        }
+        break;
+
+    case NETIF_INTERFACE_STATUS_DISCONNECTED:
+        switch(np->backend_state){
+
+        case BEST_CLOSED:
+            vif_disconnect(np);
+            break;
+
+        case BEST_DISCONNECTED:
+        case BEST_CONNECTED:
+            vif_reset(np);
+            break;
+        }
+        break;
+
+    case NETIF_INTERFACE_STATUS_CONNECTED:
+        switch(np->backend_state){
+
+        case BEST_CLOSED:
+            unexpected(np, status);
+            vif_disconnect(np);
+            vif_connect(np, status);
+            break;
+
+        case BEST_DISCONNECTED:
+            vif_connect(np, status);
+            break;
+
+        case BEST_CONNECTED:
+            //todo Do what?
+            unexpected(np, status);
             break;
         }
+        break;
+
+    case NETIF_INTERFACE_STATUS_CHANGED:
+        /* The domain controller is notifying us that a device has been
+        * added or removed.
+        */
+        break;
+
+    default:
+        WPRINTK(" Invalid netif status code %d\n", status->status);
+        break;
     }
+    vif_show(np);
+    DPRINTK("<\n");
 }
 
+/*
+ * Initialize the network control interface. 
+ */
+static void netif_driver_status(netif_fe_driver_status_t *status)
+{
+    DPRINTK("> status=%d\n", status->status);
+    netctrl.up = status->status;
+    //netctrl.interface_n = status->max_handle;
+    //netctrl.connected_n = 0;
+    netctrl_connected_count();
+}
+
+/* Receive handler for control messages. */
 static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 {
-    int respond = 1;
 
     switch ( msg->subtype )
     {
-    case CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
-        if ( msg->length != sizeof(netif_fe_interface_status_changed_t) )
+    case CMSG_NETIF_FE_INTERFACE_STATUS:
+        if ( msg->length != sizeof(netif_fe_interface_status_t) )
             goto error;
-        netif_status_change((netif_fe_interface_status_changed_t *)
-                            &msg->msg[0]);
+        netif_interface_status((netif_fe_interface_status_t *)
+                               &msg->msg[0]);
         break;
 
-    case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
-        if ( msg->length != sizeof(netif_fe_driver_status_changed_t) )
+    case CMSG_NETIF_FE_DRIVER_STATUS:
+        if ( msg->length != sizeof(netif_fe_driver_status_t) )
             goto error;
-        netif_driver_status_change((netif_fe_driver_status_changed_t *)
-                                   &msg->msg[0]);
+        netif_driver_status((netif_fe_driver_status_t *)
+                            &msg->msg[0]);
         break;
 
     error:
@@ -900,156 +1082,170 @@ static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
         break;
     }
 
-    if ( respond )
-        ctrl_if_send_response(msg);
+    ctrl_if_send_response(msg);
 }
 
 
-/* Wait for all interfaces to be connected. */
-static int wait_for_interfaces(void)
+#if 1
+/* Wait for all interfaces to be connected.
+ *
+ * This works OK, but we'd like to use the probing mode (see below).
+ */
+static int probe_interfaces(void)
 {
     int err = 0, conn = 0;
     int wait_i, wait_n = 100;
 
     DPRINTK(">\n");
 
-    for ( wait_i = 0; wait_i < wait_n; wait_i++)
-    { 
+    for ( wait_i = 0; wait_i < wait_n; wait_i++) { 
         DPRINTK("> wait_i=%d\n", wait_i);
         conn = netctrl_connected();
         if(conn) break;
+        DPRINTK("> schedule_timeout...\n");
         set_current_state(TASK_INTERRUPTIBLE);
         schedule_timeout(10);
     }
 
-    if ( conn <= 0 )
-    {
+    DPRINTK("> wait finished...\n");
+    if ( conn <= 0 ) {
         err = netctrl_err(-ENETDOWN);
-        printk(KERN_WARNING "[XEN] Failed to connect all virtual interfaces: "
-               "err=%d\n", err);
+        WPRINTK(" Failed to connect all virtual interfaces: err=%d\n", err);
     }
 
     DPRINTK("< err=%d\n", err);
 
     return err;
 }
+#else
+/* Probe for interfaces until no more are found.
+ *
+ * This is the mode we'd like to use, but at the moment it panics the kernel.
+*/
+static int probe_interfaces(void)
+{
+    int err = 0;
+    int wait_i, wait_n = 100;
+    ctrl_msg_t cmsg = {
+        .type    = CMSG_NETIF_FE,
+        .subtype = CMSG_NETIF_FE_INTERFACE_STATUS,
+        .length  = sizeof(netif_fe_interface_status_t),
+    };
+    netif_fe_interface_status_t msg = {};
+    ctrl_msg_t rmsg = {};
+    netif_fe_interface_status_t *reply = (void*)rmsg.msg;
+    int state = TASK_UNINTERRUPTIBLE;
+    u32 query = -1;
+
+    DPRINTK(">\n");
+
+    netctrl.interface_n = 0;
+    for (wait_i = 0; wait_i < wait_n; wait_i++) { 
+        DPRINTK("> wait_i=%d query=%d\n", wait_i, query);
+        msg.handle = query;
+        memcpy(cmsg.msg, &msg, sizeof(msg));
+        DPRINTK("> set_current_state...\n");
+        set_current_state(state);
+        DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
+        DPRINTK("> sending...\n");
+        err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state);
+        DPRINTK("> err=%d\n", err);
+        if(err) goto exit;
+        DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
+        if((int)reply->handle < 0){
+            // No more interfaces.
+            break;
+        }
+        query = -reply->handle - 2;
+        DPRINTK(">netif_interface_status ...\n");
+        netif_interface_status(reply);
+    }
+
+  exit:
+    if (err) {
+        err = netctrl_err(-ENETDOWN);
+        WPRINTK(" Connecting virtual network interfaces failed: err=%d\n", err);
+    }
+
+    DPRINTK("< err=%d\n", err);
+    return err;
+}
+
+#endif
 
 static int __init netif_init(void)
 {
-    ctrl_msg_t                       cmsg;
-    netif_fe_driver_status_changed_t st;
     int err = 0;
 
     if ( (start_info.flags & SIF_INITDOMAIN) ||
          (start_info.flags & SIF_NET_BE_DOMAIN) )
         return 0;
 
-    printk(KERN_INFO "Initialising Xen virtual ethernet frontend driver.\n");
-
+    IPRINTK(" Initialising virtual ethernet driver.\n");
     INIT_LIST_HEAD(&dev_list);
-
     netctrl_init();
-
     (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
                                     CALLBACK_IN_BLOCKING_CONTEXT);
-
-    /* Send a driver-UP notification to the domain controller. */
-    cmsg.type      = CMSG_NETIF_FE;
-    cmsg.subtype   = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(netif_fe_driver_status_changed_t);
-    st.status      = NETIF_DRIVER_STATUS_UP;
-    st.max_handle  = 0;
-    memcpy(cmsg.msg, &st, sizeof(st));
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-
-    err = wait_for_interfaces();
+    send_driver_status(1);
+    err = probe_interfaces();
     if ( err )
         ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
 
+    DPRINTK("< err=%d\n", err);
     return err;
 }
 
-void netif_suspend(void)
+static void vif_suspend(struct net_private *np)
 {
-#if 1 /* XXX THIS IS TEMPORARY */
-    struct net_device *dev = NULL;
-    struct net_private *np = NULL;
-    int i;
-
-/* avoid having tx/rx stuff happen until we're ready */
-
-    for(i=0;i<netctrl.interface_n;i++)
-    {
-       char name[32];
+    // Avoid having tx/rx stuff happen until we're ready.
+    DPRINTK(">\n");
+    free_irq(np->irq, np->dev);
+    unbind_evtchn_from_irq(np->evtchn);
+    DPRINTK("<\n");
+}
 
-       sprintf(name,"eth%d",i);
-       dev = __dev_get_by_name(name);
+static void vif_resume(struct net_private *np)
+{
+    // Connect regardless of whether IFF_UP flag set.
+    // Stop bad things from happening until we're back up.
+    DPRINTK(">\n");
+    np->backend_state = BEST_DISCONNECTED;
+    memset(np->tx, 0, PAGE_SIZE);
+    memset(np->rx, 0, PAGE_SIZE);
+    
+    send_interface_connect(np);
+    DPRINTK("<\n");
+}
 
-       if ( dev )
-       {
-           np  = dev->priv;
-           free_irq(np->irq, dev);
-            unbind_evtchn_from_irq(np->evtchn);
-       }    
+void netif_suspend(void)
+{
+#if 1 /* XXX THIS IS TEMPORARY */
+    struct list_head *ent;
+    struct net_private *np;
+    
+    DPRINTK(">\n");
+    list_for_each(ent, &dev_list){
+        np = list_entry(ent, struct net_private, list);
+        vif_suspend(np);
     }
+    DPRINTK("<\n");
 #endif
 }
 
 void netif_resume(void)
 {
-    ctrl_msg_t                   cmsg;
-    netif_fe_interface_connect_t up;
-    struct net_device *dev = NULL;
-    struct net_private *np = NULL;
-    int i;
-
 #if 1
     /* XXX THIS IS TEMPORARY */
+    struct list_head *ent;
+    struct net_private *np;
 
-    for(i=0;i<netctrl.interface_n;i++)    
-    {
-       char name[32];
-
-       sprintf(name,"eth%d",i);
-       dev = __dev_get_by_name(name);
-
-       if ( dev ) // connect regardless of whether IFF_UP flag set
-       {
-           np  = dev->priv;
-
-           // stop bad things from happening until we're back up
-           np->backend_state = BEST_DISCONNECTED;
-           
-           memset(np->tx,0,PAGE_SIZE);
-           memset(np->rx,0,PAGE_SIZE);
-
-           cmsg.type      = CMSG_NETIF_FE;
-           cmsg.subtype   = CMSG_NETIF_FE_INTERFACE_CONNECT;
-           cmsg.length    = sizeof(netif_fe_interface_connect_t);
-           up.handle      = np->handle;
-           up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
-           up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
-           memcpy(cmsg.msg, &up, sizeof(up));
-
-           /* Tell the controller to bring up the interface. */
-           ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-       }
+    DPRINTK(">\n");
+    list_for_each(ent, &dev_list){
+        np = list_entry(ent, struct net_private, list);
+        vif_resume(np);
     }
+    DPRINTK("<\n");
 #endif     
-
-
-#if 0
-    /* Send a driver-UP notification to the domain controller. */
-    cmsg.type      = CMSG_NETIF_FE;
-    cmsg.subtype   = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
-    cmsg.length    = sizeof(netif_fe_driver_status_changed_t);
-    st.status      = NETIF_DRIVER_STATUS_UP;
-    st.max_handle  = 0;
-    memcpy(cmsg.msg, &st, sizeof(st));
-    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-#endif
-
-
 }
 
 
index 7bf82e483a091d0992d4b478511cc60d3be5b80c..813f3574640a85e41ff1bd31f80d6d2e90a7db04 100644 (file)
@@ -324,11 +324,11 @@ static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
 
     switch ( TYPE(xum->msg.type, xum->msg.subtype) )
     {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(blkif_fe_driver_status_changed_t, max_handle, u32);
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
+        P2C(blkif_fe_driver_status_t, max_handle, u32);
         break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, max_handle, u32);
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
+        P2C(netif_fe_driver_status_t, max_handle, u32);
         break;
     }
 
@@ -352,13 +352,13 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
 
     switch ( TYPE(xum->msg.type, xum->msg.subtype) )
     {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(blkif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(blkif_fe_interface_status_changed_t, evtchn, Int, Long);
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
+        C2P(blkif_fe_interface_status_t, handle, Int, Long);
+        C2P(blkif_fe_interface_status_t, status, Int, Long);
+        C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
         return dict;
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_fe_driver_status_changed_t, status, Int, Long);
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
+        C2P(blkif_fe_driver_status_t, status, Int, Long);
         return dict;
     case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
         C2P(blkif_fe_interface_connect_t, handle,      Int, Long);
@@ -419,23 +419,23 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
         C2P(blkif_be_vbd_shrink_t, vdevice,      Int, Long);
         C2P(blkif_be_vbd_shrink_t, status,       Int, Long);
         return dict;
-    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(blkif_be_driver_status_changed_t, status, Int, Long);
+    case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
+        C2P(blkif_be_driver_status_t, status, Int, Long);
         return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        C2P(netif_fe_interface_status_changed_t, handle, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, status, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, evtchn, Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[0], Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[1], Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[2], Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[3], Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[4], Int, Long);
-        C2P(netif_fe_interface_status_changed_t, mac[5], Int, Long);
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
+        C2P(netif_fe_interface_status_t, handle, Int, Long);
+        C2P(netif_fe_interface_status_t, status, Int, Long);
+        C2P(netif_fe_interface_status_t, evtchn, Int, Long);
+        C2P(netif_fe_interface_status_t, mac[0], Int, Long);
+        C2P(netif_fe_interface_status_t, mac[1], Int, Long);
+        C2P(netif_fe_interface_status_t, mac[2], Int, Long);
+        C2P(netif_fe_interface_status_t, mac[3], Int, Long);
+        C2P(netif_fe_interface_status_t, mac[4], Int, Long);
+        C2P(netif_fe_interface_status_t, mac[5], Int, Long);
         return dict;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        C2P(netif_fe_driver_status_changed_t, status,        Int, Long);
-        C2P(netif_fe_driver_status_changed_t, max_handle,    Int, Long);
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
+        C2P(netif_fe_driver_status_t, status,        Int, Long);
+        C2P(netif_fe_driver_status_t, max_handle,    Int, Long);
         return dict;
     case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
         C2P(netif_fe_interface_connect_t, handle,         Int, Long);
@@ -468,8 +468,8 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
         C2P(netif_be_disconnect_t, netif_handle, Int, Long);
         C2P(netif_be_disconnect_t, status,       Int, Long);
         return dict;
-    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED):
-        C2P(netif_be_driver_status_changed_t, status, Int, Long);
+    case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
+        C2P(netif_be_driver_status_t, status, Int, Long);
         return dict;
     }
 
@@ -543,11 +543,11 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
 
     switch ( TYPE(type, subtype) )
     {
-    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(blkif_fe_interface_status_changed_t, handle, u32);
-        P2C(blkif_fe_interface_status_changed_t, status, u32);
-        P2C(blkif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(blkif_fe_interface_status_changed_t, domid,  u16);
+    case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
+        P2C(blkif_fe_interface_status_t, handle, u32);
+        P2C(blkif_fe_interface_status_t, status, u32);
+        P2C(blkif_fe_interface_status_t, evtchn, u16);
+        P2C(blkif_fe_interface_status_t, domid,  u16);
         break;
     case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
         P2C(blkif_be_create_t, domid,        u32);
@@ -591,17 +591,17 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
         P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
         P2C(blkif_be_vbd_shrink_t, vdevice,      blkif_vdev_t);
         break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED):
-        P2C(netif_fe_interface_status_changed_t, handle, u32);
-        P2C(netif_fe_interface_status_changed_t, status, u32);
-        P2C(netif_fe_interface_status_changed_t, evtchn, u16);
-        P2C(netif_fe_interface_status_changed_t, domid,  u16);
-        P2C(netif_fe_interface_status_changed_t, mac[0], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[1], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[2], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[3], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[4], u8);
-        P2C(netif_fe_interface_status_changed_t, mac[5], u8);
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
+        P2C(netif_fe_interface_status_t, handle, u32);
+        P2C(netif_fe_interface_status_t, status, u32);
+        P2C(netif_fe_interface_status_t, evtchn, u16);
+        P2C(netif_fe_interface_status_t, domid,  u16);
+        P2C(netif_fe_interface_status_t, mac[0], u8);
+        P2C(netif_fe_interface_status_t, mac[1], u8);
+        P2C(netif_fe_interface_status_t, mac[2], u8);
+        P2C(netif_fe_interface_status_t, mac[3], u8);
+        P2C(netif_fe_interface_status_t, mac[4], u8);
+        P2C(netif_fe_interface_status_t, mac[5], u8);
         break;
     case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
         P2C(netif_be_create_t, domid,        u32);
@@ -628,9 +628,9 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
         P2C(netif_be_disconnect_t, domid,        u32);
         P2C(netif_be_disconnect_t, netif_handle, u32);
         break;
-    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED):
-        P2C(netif_fe_driver_status_changed_t, status,        u32);
-        P2C(netif_fe_driver_status_changed_t, max_handle,    u32);
+    case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
+        P2C(netif_fe_driver_status_t, status,        u32);
+        P2C(netif_fe_driver_status_t, max_handle,    u32);
         break;
     }
 
index 58b17d2933f76bf3a4972a1337d9890fcb6688a8..ef1a3c2135814a3249099f7ca09d503f8cd78a12 100644 (file)
@@ -239,14 +239,14 @@ class XendDomain:
         destroyed = 0
         for d in casualties:
             id = str(d['dom'])
-            log.debug('XendDomain>reap> domain died id=%s', id)
+            dominfo = self.domain_by_id.get(id)
+            name = (dominfo and dominfo.name) or '??'
+            log.debug('XendDomain>reap> domain died name=%s id=%s', name, id)
             if d['shutdown']:
                 reason = XendDomainInfo.shutdown_reason(d['shutdown_reason'])
                 log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason)
-                dominfo = self.domain_by_id.get(id)
-                name = (dominfo and dominfo.name) or '??'
                 if reason in ['suspend']:
-                    if dominfo.is_terminated():
+                    if dominfo and dominfo.is_terminated():
                         log.debug('XendDomain>reap> Suspended domain died id=%s', id)
                     else:
                         eserver.inject('xend.domain.suspended', [name, id])
index 17a002c6653c8da0413f40e4abe50d7a8244c963..b24bf186ab409afa63aef28beddd12064a167314 100644 (file)
@@ -155,6 +155,7 @@ def make_disk(vm, config, uname, dev, mode, recreate=0):
     @param recreate: recreate flag (after xend restart)
     @return: deferred
     """
+    idx = vm.next_device_index('vbd')
     segments = lookup_disk_uname(uname)
     if not segments:
         raise VmError("vbd: Segments not found: uname=%s" % uname)
@@ -166,7 +167,7 @@ def make_disk(vm, config, uname, dev, mode, recreate=0):
     if not vdev:
         raise VmError("vbd: Device not found: uname=%s dev=%s" % (uname, dev))
     ctrl = xend.blkif_create(vm.dom, recreate=recreate)
-    return ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate)
+    return ctrl.attachDevice(idx, config, vdev, mode, segment, recreate=recreate)
         
 def vif_up(iplist):
     """send an unsolicited ARP reply for all non link-local IP addresses.
index 60708e24a97311a2732f452d643bdc31d058d4fd..339b99ee123110fd744cdbf7dda82c6e9832b98c 100755 (executable)
@@ -19,19 +19,19 @@ class BlkifBackendController(controller.BackendController):
     def __init__(self, factory, dom):
         controller.BackendController.__init__(self, factory, dom)
         self.addMethod(CMSG_BLKIF_BE,
-                       CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED,
-                       self.recv_be_driver_status_changed)
+                       CMSG_BLKIF_BE_DRIVER_STATUS,
+                       self.recv_be_driver_status)
         self.registerChannel()
 
-    def recv_be_driver_status_changed(self, msg, req):
-        """Request handler for be_driver_status_changed messages.
+    def recv_be_driver_status(self, msg, req):
+        """Request handler for be_driver_status messages.
         
         @param msg: message
         @type  msg: xu message
         @param req: request flag (true if the msg is a request)
         @type  req: bool
         """
-        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
+        val = unpackMsg('blkif_be_driver_status_t', msg)
         status = val['status']
 
 class BlkifBackendInterface(controller.BackendInterface):
@@ -45,10 +45,23 @@ class BlkifBackendInterface(controller.BackendInterface):
         controller.BackendInterface.__init__(self, ctrl, dom, handle)
         self.connected = 0
         self.evtchn = None
+        self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
 
     def __str__(self):
         return '<BlkifBackendInterface %d %d>' % (self.controller.dom, self.dom)
 
+    def getEventChannelBackend(self):
+        val = 0
+        if self.evtchn:
+            val = self.evtchn['port1']
+        return val
+
+    def getEventChannelFrontend(self):
+        val = 0
+        if self.evtchn:
+            val = self.evtchn['port2']
+        return val
+
     def connect(self, recreate=0):
         """Connect to the blkif control interface.
 
@@ -105,7 +118,7 @@ class BlkifBackendInterface(controller.BackendInterface):
         msg = packMsg('blkif_be_connect_t',
                       { 'domid'        : self.controller.dom,
                         'blkif_handle' : self.handle,
-                        'evtchn'       : self.evtchn['port1'],
+                        'evtchn'       : self.getEventChannelBackend(),
                         'shmem_frame'  : val['shmem_frame'] })
         d = defer.Deferred()
         d.addCallback(self.respond_be_connect)
@@ -118,31 +131,29 @@ class BlkifBackendInterface(controller.BackendInterface):
         @type  msg: xu message
         """
         val = unpackMsg('blkif_be_connect_t', msg)
-        self.send_fe_interface_status_changed()
+        self.status = BLKIF_INTERFACE_STATUS_CONNECTED
+        self.send_fe_interface_status()
             
-    def send_fe_interface_status_changed(self, response=None):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
+    def send_fe_interface_status(self, response=None):
+        msg = packMsg('blkif_fe_interface_status_t',
                       { 'handle' : self.handle,
-                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
+                        'status' : self.status,
                         'domid'  : self.dom,
-                        'evtchn' : self.evtchn['port2'] })
+                        'evtchn' : self.getEventChannelFrontend() })
         self.controller.writeRequest(msg, response=response)
 
     def interfaceDisconnected(self):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : self.handle,
-                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
-                        'domid'  : self.dom,
-                        'evtchn' : 0 })
-        self.controller.writeRequest(msg)
+        self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
+        #todo?: Do this: self.evtchn = None
+        self.send_fe_interface_status()
         
     def interfaceChanged(self):
         """Notify the front-end that devices have been added or removed.
         The front-end should then probe for devices.
         """
-        msg = packMsg('blkif_fe_interface_status_changed_t',
+        msg = packMsg('blkif_fe_interface_status_t',
                       { 'handle' : self.handle,
-                        'status' : BLKIF_INTERFACE_STATUS_CHANGED,
+                        'status' : BLKIF_INTERFACE_STATUS,
                         'domid'  : self.dom,
                         'evtchn' : 0 })
         self.controller.writeRequest(msg)
@@ -199,25 +210,25 @@ class BlkifControllerFactory(controller.SplitControllerFactory):
         blkif = self.getControllerByDom(dom)
         return (blkif and blkif.getDevices()) or []
 
-    def getDomainDevice(self, dom, vdev):
+    def getDomainDevice(self, dom, idx):
         """Get a block device from a domain.
 
         @param dom: domain
         @type  dom: int
-        @param vdev: device index
-        @type  vdev: int
+        @param idx: device index
+        @type  idx: int
         @return: device
         @rtype:  device
         """
         blkif = self.getControllerByDom(dom)
-        return (blkif and blkif.getDevice(vdev)) or None
+        return (blkif and blkif.getDevice(idx)) or None
 
 class BlkDev(controller.SplitDev):
     """Info record for a block device.
     """
 
-    def __init__(self, ctrl, config, vdev, mode, segment):
-        controller.SplitDev.__init__(self,  segment['device'], ctrl)
+    def __init__(self, idx, ctrl, config, vdev, mode, segment):
+        controller.SplitDev.__init__(self, idx, ctrl)
         self.config = config
         self.dev = None
         self.uname = None
@@ -251,7 +262,7 @@ class BlkDev(controller.SplitDev):
 
         @param change: change flag
         """
-        log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
+        log.debug("Destroying vbd domain=%d idx=%s", self.controller.dom, self.idx)
         d = self.send_be_vbd_destroy()
         if change:
             d.addCallback(lambda val: self.interfaceChanged())
@@ -345,10 +356,9 @@ class BlkifController(controller.SplitController):
         Do not call directly - use createController() on the factory instead.
         """
         controller.SplitController.__init__(self, factory, dom)
-        self.devices = {}
         self.addMethod(CMSG_BLKIF_FE,
-                       CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED,
-                       self.recv_fe_driver_status_changed)
+                       CMSG_BLKIF_FE_DRIVER_STATUS,
+                       self.recv_fe_driver_status)
         self.addMethod(CMSG_BLKIF_FE,
                        CMSG_BLKIF_FE_INTERFACE_CONNECT,
                        self.recv_fe_interface_connect)
@@ -358,13 +368,7 @@ class BlkifController(controller.SplitController):
         val = ['blkif', ['dom', self.dom]]
         return val
 
-    def getDevices(self):
-        return self.devices.values()
-
-    def getDevice(self, vdev):
-        return self.devices.get(vdev)
-
-    def addDevice(self, config, vdev, mode, segment):
+    def addDevice(self, idx, config, vdev, mode, segment):
         """Add a device to the device table.
 
         @param vdev:     device index
@@ -376,20 +380,18 @@ class BlkifController(controller.SplitController):
         @return: device
         @rtype:  BlkDev
         """
-        if vdev in self.devices:
-            raise XendError('device exists: ' + str(vdev))
-        dev = BlkDev(self, config, vdev, mode, segment)
-        self.devices[vdev] = dev
+        if idx in self.devices:
+            raise XendError('device exists: ' + str(idx))
+        dev = BlkDev(idx, self, config, vdev, mode, segment)
+        self.devices[idx] = dev
         return dev
 
-    def delDevice(self, vdev):
-        if vdev in self.devices:
-            del self.devices[vdev]
-
-    def attachDevice(self, config, vdev, mode, segment, recreate=0):
+    def attachDevice(self, idx, config, vdev, mode, segment, recreate=0):
         """Attach a device to the specified interface.
         On success the returned deferred will be called with the device.
 
+        @param idx:      device id
+        @param config:   device configuration
         @param vdev:     device index
         @type  vdev:     int
         @param mode:     read/write mode
@@ -401,7 +403,7 @@ class BlkifController(controller.SplitController):
         @return: deferred
         @rtype:  Deferred
         """
-        dev = self.addDevice(config, vdev, mode, segment)
+        dev = self.addDevice(idx, config, vdev, mode, segment)
         if recreate:
             d = defer.succeed(dev)
         else:
@@ -425,8 +427,9 @@ class BlkifController(controller.SplitController):
         for backend in self.getBackendInterfaces():
             backend.destroy()
 
-    def recv_fe_driver_status_changed(self, msg, req):
-        val = unpackMsg('blkif_fe_driver_status_changed_t', msg)
+    def recv_fe_driver_status(self, msg, req):
+        val = unpackMsg('blkif_fe_driver_status_t', msg)
+        print 'recv_fe_driver_status>', val
         for backend in self.getBackendInterfaces():
             backend.interfaceDisconnected()
 
@@ -439,5 +442,6 @@ class BlkifController(controller.SplitController):
         else:
             log.error('interface connect on unknown interface: handle=%d', handle)
 
+
     
 
index 71855d87555ba0b050af9857bafff8b507980ad3..3721b9b3b3349214ee71fcf095ce23c14ee36313 100755 (executable)
@@ -522,6 +522,9 @@ class BackendInterface:
     def writeRequest(self, msg, response=None):
         return self.backend.writeRequest(msg, response=response)
 
+    def writeResponse(self, msg):
+        return self.backend.writeResponse(msg)
+    
     def close(self):
         self.backend.deregisterInterface(self)
         self.controller.backendInterfaceClosed(self)
@@ -536,6 +539,60 @@ class SplitController(Controller):
         Controller.__init__(self, factory, dom)
         self.backendInterfaces = {}
         self.backendHandle = 0
+        self.devices = {}
+
+    def getDevices(self):
+        """Get a list of the devices..
+        """
+        return self.devices.values()
+
+    def delDevice(self, idx):
+        """Remove the device with the given index from the device table.
+
+        @param idx device index
+        """
+        if idx in self.devices:
+            del self.devices[idx]
+
+    def getDevice(self, idx):
+        """Get the device with a given index.
+
+        @param idx device index
+        @return device (or None)
+        """
+        return self.devices.get(idx)
+
+    def findDevice(self, idx):
+        """Find a device. If idx is non-negative,
+        get the device with the given index. If idx is negative,
+        look for the device with least index greater than -idx - 2.
+        For example, if idx is -2, look for devices with index
+        greater than 0, i.e. 1 or above.
+
+        @param idx device index
+        @return device (or None)
+        """
+        if idx < 0:
+            idx = -idx - 2
+            val = None
+            for dev in self.devices.values():
+                if dev.idx <= idx: continue
+                if (val is None) or (dev.idx < val.idx):
+                    val = dev
+        else:
+            val = getDevice(idx)
+        return val
+
+    def getMaxDeviceIdx(self):
+        """Get the maximum id used by devices.
+
+        @return maximum idx
+        """
+        maxIdx = 0
+        for dev in self.devices:
+            if dev.idx > maxIdx:
+                maxIdx = dev.idx
+        return maxIdx
         
     def getBackendInterfaces(self):
         return self.backendInterfaces.values()
index fb94214a6461e9fdef1e2db062b2f9e338845198..da4980fc960d5f3bb4bd5ba50573d7415d0c3a7d 100644 (file)
@@ -29,70 +29,106 @@ msg_formats.update(console_formats)
 CMSG_BLKIF_BE = 1
 CMSG_BLKIF_FE = 2
 
-CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
-CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
-
-CMSG_BLKIF_BE_CREATE      = 0
-CMSG_BLKIF_BE_DESTROY     = 1
-CMSG_BLKIF_BE_CONNECT     = 2
-CMSG_BLKIF_BE_DISCONNECT  = 3
-CMSG_BLKIF_BE_VBD_CREATE  = 4
-CMSG_BLKIF_BE_VBD_DESTROY = 5
-CMSG_BLKIF_BE_VBD_GROW    = 6
-CMSG_BLKIF_BE_VBD_SHRINK  = 7
-CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
-
-BLKIF_DRIVER_STATUS_DOWN  = 0
-BLKIF_DRIVER_STATUS_UP    = 1
-
-BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-BLKIF_INTERFACE_STATUS_CHANGED      = 3 #/* A device has been added or removed. */
-
-BLKIF_BE_STATUS_OKAY                = 0
-BLKIF_BE_STATUS_ERROR               = 1
-BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
-BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
-BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
-BLKIF_BE_STATUS_VBD_EXISTS          = 5
-BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
-BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
-BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
-BLKIF_BE_STATUS_MAPPING_ERROR       = 9
+CMSG_BLKIF_FE_INTERFACE_STATUS      =  0
+CMSG_BLKIF_FE_DRIVER_STATUS         = 32
+CMSG_BLKIF_FE_INTERFACE_CONNECT     = 33
+CMSG_BLKIF_FE_INTERFACE_DISCONNECT  = 34
+CMSG_BLKIF_FE_INTERFACE_QUERY       = 35
+
+CMSG_BLKIF_BE_CREATE                =  0
+CMSG_BLKIF_BE_DESTROY               =  1
+CMSG_BLKIF_BE_CONNECT               =  2
+CMSG_BLKIF_BE_DISCONNECT            =  3
+CMSG_BLKIF_BE_VBD_CREATE            =  4
+CMSG_BLKIF_BE_VBD_DESTROY           =  5
+CMSG_BLKIF_BE_VBD_GROW              =  6
+CMSG_BLKIF_BE_VBD_SHRINK            =  7
+CMSG_BLKIF_BE_DRIVER_STATUS         = 32
+
+BLKIF_DRIVER_STATUS_DOWN            =  0
+BLKIF_DRIVER_STATUS_UP              =  1
+
+BLKIF_INTERFACE_STATUS_CLOSED       =  0 #/* Interface doesn't exist.    */
+BLKIF_INTERFACE_STATUS_DISCONNECTED =  1 #/* Exists but is disconnected. */
+BLKIF_INTERFACE_STATUS_CONNECTED    =  2 #/* Exists and is connected.    */
+BLKIF_INTERFACE_STATUS_CHANGED      =  3 #/* A device has been added or removed. */
+
+BLKIF_BE_STATUS_OKAY                =  0
+BLKIF_BE_STATUS_ERROR               =  1
+BLKIF_BE_STATUS_INTERFACE_EXISTS    =  2
+BLKIF_BE_STATUS_INTERFACE_NOT_FOUND =  3
+BLKIF_BE_STATUS_INTERFACE_CONNECTED =  4
+BLKIF_BE_STATUS_VBD_EXISTS          =  5
+BLKIF_BE_STATUS_VBD_NOT_FOUND       =  6
+BLKIF_BE_STATUS_OUT_OF_MEMORY       =  7
+BLKIF_BE_STATUS_EXTENT_NOT_FOUND    =  8
+BLKIF_BE_STATUS_MAPPING_ERROR       =  9
 
 blkif_formats = {
     'blkif_be_connect_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
+    # Connect be to fe (in response to blkif_fe_interface_connect_t).
 
     'blkif_be_create_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
+    # Create be.
 
     'blkif_be_disconnect_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
+    # Disconnect be from fe.
 
     'blkif_be_destroy_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
+    # Destroy be (after disconnect).
+    # Make be do this even if no disconnect (and destroy all vbd too).
 
     'blkif_be_vbd_create_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
+    # Create a vbd device.
 
     'blkif_be_vbd_grow_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
+    # Change the size of a vbd device. Remove?
+    # Do in one go in blkif_be_vbd_create_t.
 
     'blkif_be_vbd_destroy_t':
     (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
-
-    'blkif_fe_interface_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
-
-    'blkif_fe_driver_status_changed_t':
-    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
+    # Destroy a vbd.
+
+    # Add message to query be for state and vbds.
+
+    'blkif_fe_interface_status_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS),
+    # Notify device status to fe.
+    # Also used to notify 'any' device change with status BLKIF_INTERFACE_STATUS_CHANGED.
+    # Rename to blkif_fe_interface_status.
+
+    'blkif_fe_driver_status_t':
+    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS),
+    # Comes from fe, treated as notifying that fe has come up/changed.
+    # Xend sets be(s) to BLKIF_INTERFACE_STATUS_DISCONNECTED,
+    # sends blkif_fe_interface_status_t to fe (from each be).
+    #
+    # Rename to blkif_fe_driver_status.
+    # Reply with i/f count.
+    # The i/f sends probes (using -ve trick), we reply with the info.
 
     'blkif_fe_interface_connect_t':
     (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
+    # Comes from fe, passing shmem frame to use for be.
+    # fe sends when gets blkif_fe_interface_status_t with state NETIF_INTERFACE_STATUS_DISCONNECTED.
+    # Xend creates event channel and notifies be.
+    # Then notifies fe of event channel with blkif_fe_interface_status_t.
+
+    # Add message to kick fe to probe for devices.
+    # Just report new devices to fe?
+
+    # 
+    # Add message for fe to probe a device.
+    # And probing with id -1 should return first.
+    # And probing with id -n should return first device with id > n.
+    
+    # Add message to query fe for state and vbds.
 }
 
 msg_formats.update(blkif_formats)
@@ -104,24 +140,25 @@ msg_formats.update(blkif_formats)
 CMSG_NETIF_BE = 3
 CMSG_NETIF_FE = 4
 
-CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
-CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
-CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
-CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
+CMSG_NETIF_FE_INTERFACE_STATUS      =  0
+CMSG_NETIF_FE_DRIVER_STATUS         = 32
+CMSG_NETIF_FE_INTERFACE_CONNECT     = 33
+CMSG_NETIF_FE_INTERFACE_DISCONNECT  = 34
+CMSG_NETIF_FE_INTERFACE_QUERY       = 35
 
-CMSG_NETIF_BE_CREATE      = 0
-CMSG_NETIF_BE_DESTROY     = 1
-CMSG_NETIF_BE_CONNECT     = 2
-CMSG_NETIF_BE_DISCONNECT  = 3
-CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
+CMSG_NETIF_BE_CREATE                =  0
+CMSG_NETIF_BE_DESTROY               =  1
+CMSG_NETIF_BE_CONNECT               =  2
+CMSG_NETIF_BE_DISCONNECT            =  3
+CMSG_NETIF_BE_DRIVER_STATUS         = 32
 
-NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
-NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
-NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
-NETIF_INTERFACE_STATUS_CHANGED      = 3 #/* A device has been added or removed. */
+NETIF_INTERFACE_STATUS_CLOSED       =  0 #/* Interface doesn't exist.    */
+NETIF_INTERFACE_STATUS_DISCONNECTED =  1 #/* Exists but is disconnected. */
+NETIF_INTERFACE_STATUS_CONNECTED    =  2 #/* Exists and is connected.    */
+NETIF_INTERFACE_STATUS_CHANGED      =  3 #/* A device has been added or removed. */
 
-NETIF_DRIVER_STATUS_DOWN   = 0
-NETIF_DRIVER_STATUS_UP     = 1
+NETIF_DRIVER_STATUS_DOWN            =  0
+NETIF_DRIVER_STATUS_UP              =  1
 
 netif_formats = {
     'netif_be_connect_t':
@@ -136,17 +173,17 @@ netif_formats = {
     'netif_be_destroy_t':
     (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
 
-    'netif_be_driver_status_changed_t':
-    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
+    'netif_be_driver_status_t':
+    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS),
 
-    'netif_fe_driver_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
+    'netif_fe_driver_status_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS),
 
     'netif_fe_interface_connect_t':
     (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
 
-    'netif_fe_interface_status_changed_t':
-    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
+    'netif_fe_interface_status_t':
+    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS),
     }
 
 msg_formats.update(netif_formats)
@@ -241,13 +278,15 @@ def unpackMsg(ty, msg):
         macs = []
         for (k, v) in args.items():
             if k.startswith('mac['):
-                macs += k
+                macs.append(k)
                 i = int(k[4:5])
                 mac[i] = v
             else:
                 pass
         if macs:
             args['mac'] = mac
+            print 'macs=', macs
+            print 'args=', args
             for k in macs:
                 del args[k]
     if DEBUG:
index 84f569d830467eb766182bb9a96bddf9e05b57aa..38e722347aaeb9bed475b6e220b351993de29938 100755 (executable)
@@ -24,12 +24,12 @@ class NetifBackendController(controller.BackendController):
     def __init__(self, ctrl, dom):
         controller.BackendController.__init__(self, ctrl, dom)
         self.addMethod(CMSG_NETIF_BE,
-                       CMSG_NETIF_BE_DRIVER_STATUS_CHANGED,
-                       self.recv_be_driver_status_changed)
+                       CMSG_NETIF_BE_DRIVER_STATUS,
+                       self.recv_be_driver_status)
         self.registerChannel()
 
-    def recv_be_driver_status_changed(self, msg, req):
-        val = unpackMsg('netif_be_driver_status_changed_t', msg)
+    def recv_be_driver_status(self, msg, req):
+        val = unpackMsg('netif_be_driver_status_t', msg)
         status = val['status']
 
 class NetifBackendInterface(controller.BackendInterface):
@@ -98,11 +98,12 @@ class NetDev(controller.SplitDev):
     """Info record for a network device.
     """
 
-    def __init__(self, ctrl, vif, config):
+    def __init__(self, vif, ctrl, config):
         controller.SplitDev.__init__(self, vif, ctrl)
         self.vif = vif
         self.evtchn = None
         self.configure(config)
+        self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
 
     def _get_config_mac(self, config):
         vmac = sxp.child_value(config, 'mac')
@@ -245,6 +246,18 @@ class NetDev(controller.SplitDev):
         d.addCallback(self.respond_be_create)
         return d
 
+    def getEventChannelBackend(self):
+        val = 0
+        if self.evtchn:
+            val = self.evtchn['port1']
+        return val
+
+    def getEventChannelFrontend(self):
+        val = 0
+        if self.evtchn:
+            val = self.evtchn['port2']
+        return val
+
     def send_be_create(self):
         d = defer.Deferred()
         msg = packMsg('netif_be_create_t',
@@ -264,11 +277,12 @@ class NetDev(controller.SplitDev):
 
         @param change: change flag
         """
+        self.status = NETIF_INTERFACE_STATUS_CLOSED
         def cb_destroy(val):
             self.send_be_destroy()
             self.getBackendInterface().close()
             if change:
-                self.interfaceChanged()
+                self.reportStatus()
         log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
         self.vifctl('down')
         d = self.send_be_disconnect()
@@ -295,7 +309,7 @@ class NetDev(controller.SplitDev):
         msg = packMsg('netif_be_connect_t',
                       { 'domid'          : self.controller.dom,
                         'netif_handle'   : self.vif,
-                        'evtchn'         : self.evtchn['port1'],
+                        'evtchn'         : self.getEventChannelBackend(),
                         'tx_shmem_frame' : val['tx_shmem_frame'],
                         'rx_shmem_frame' : val['rx_shmem_frame'] })
         d = defer.Deferred()
@@ -306,34 +320,25 @@ class NetDev(controller.SplitDev):
         val = unpackMsg('netif_be_connect_t', msg)
         dom = val['domid']
         vif = val['netif_handle']
-        msg = packMsg('netif_fe_interface_status_changed_t',
-                      { 'handle' : self.vif,
-                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : self.evtchn['port2'],
-                        'domid'  : self.backendDomain,
-                        'mac'    : self.mac })
-        self.controller.writeRequest(msg)
+        self.status = NETIF_INTERFACE_STATUS_CONNECTED
+        self.reportStatus()
 
-    def attach_fe_device(self):
-        msg = packMsg('netif_fe_interface_status_changed_t',
+    def reportStatus(self, resp=0):
+        msg = packMsg('netif_fe_interface_status_t',
                       { 'handle' : self.vif,
-                        'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
-                        'evtchn' : 0,
+                        'status' : self.status,
+                        'evtchn' : self.getEventChannelFrontend(),
                         'domid'  : self.backendDomain,
                         'mac'    : self.mac })
-        self.controller.writeRequest(msg)
+        if resp:
+            self.controller.writeResponse(msg)
+        else:
+            self.controller.writeRequest(msg)
 
     def interfaceChanged(self):
         """Notify the font-end that a device has been added or removed.
-        The front-end should then probe the devices.
         """
-        msg = packMsg('netif_fe_interface_status_changed_t',
-                      { 'handle' : self.vif,
-                        'status' : NETIF_INTERFACE_STATUS_CHANGED,
-                        'evtchn' : 0,
-                        'domid'  : self.backendDomain,
-                        'mac'    : self.mac })
-        self.controller.writeRequest(msg)
+        self.reportStatus()
         
 class NetifController(controller.SplitController):
     """Network interface controller. Handles all network devices for a domain.
@@ -343,8 +348,11 @@ class NetifController(controller.SplitController):
         controller.SplitController.__init__(self, factory, dom)
         self.devices = {}
         self.addMethod(CMSG_NETIF_FE,
-                       CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
-                       self.recv_fe_driver_status_changed)
+                       CMSG_NETIF_FE_DRIVER_STATUS,
+                       self.recv_fe_driver_status)
+        self.addMethod(CMSG_NETIF_FE,
+                       CMSG_NETIF_FE_INTERFACE_STATUS,
+                       self.recv_fe_interface_status)
         self.addMethod(CMSG_NETIF_FE,
                        CMSG_NETIF_FE_INTERFACE_CONNECT,
                        self.recv_fe_interface_connect)
@@ -359,19 +367,6 @@ class NetifController(controller.SplitController):
         """
         controller.Controller.lostChannel(self)
 
-    def getDevices(self):
-        """Get a list of the devices.
-        """
-        return self.devices.values()
-
-    def getDevice(self, vif):
-        """Get a device.
-
-        @param vif: device index
-        @return: device (or None)
-        """
-        return self.devices.get(vif)
-
     def addDevice(self, vif, config):
         """Add a network interface.
 
@@ -381,14 +376,10 @@ class NetifController(controller.SplitController):
         """
         if vif in self.devices:
             raise XendError('device exists:' + str(vif))
-        dev = NetDev(self, vif, config)
+        dev = NetDev(vif, self, config)
         self.devices[vif] = dev
         return dev
 
-    def delDevice(self, vif):
-        if vif in self.devices:
-            del self.devices[vif]
-
     def destroy(self):
         """Destroy the controller and all devices.
         """
@@ -415,23 +406,64 @@ class NetifController(controller.SplitController):
             d = dev.attach()
         return d
 
-    def recv_fe_driver_status_changed(self, msg, req):
+    def recv_fe_driver_status(self, msg, req):
         if not req: return
-        msg = packMsg('netif_fe_driver_status_changed_t',
+        print
+        print 'recv_fe_driver_status>'
+        msg = packMsg('netif_fe_driver_status_t',
                       { 'status'     : NETIF_DRIVER_STATUS_UP,
                         ## FIXME: max_handle should be max active interface id
-                        'max_handle' : len(self.devices) })
-        self.writeRequest(msg)
-        for dev in self.devices.values():
-            dev.attach_fe_device()
+                        'max_handle' : len(self.devices)
+                        #'max_handle' : self.getMaxDeviceIdx()
+                        })
+        # Two ways of doing it:
+        # 1) front-end requests driver status, we reply with the interface count,
+        #    front-end polls the interfaces,
+        #    front-end checks they are all up
+        # 2) front-end requests driver status, we reply (with anything),
+        #    we notify the interfaces,
+        #    we notify driver status up with the count
+        #    front-end checks they are all up
+        #
+        # We really want to use 1), but at the moment the xenU kernel panics
+        # in that mode, so we're sticking to 2) for now.
+        resp = 0
+        if resp:
+            self.writeResponse(msg)
+        else:
+            for dev in self.devices.values():
+                dev.reportStatus()
+            self.writeRequest(msg)
+        return resp
+
+    def recv_fe_interface_status(self, msg, req):
+        if not req: return
+        print
+        val = unpackMsg('netif_fe_interface_status_t', msg)
+        print "recv_fe_interface_status>", val
+        vif = val['handle']
+        dev = self.findDevice(vif)
+        if dev:
+            print 'recv_fe_interface_status>', 'dev=', dev
+            dev.reportStatus(resp=1)
+        else:
+            msg = packMsg('netif_fe_interface_status_t',
+                          { 'handle' : -1,
+                            'status' : NETIF_INTERFACE_STATUS_CLOSED,
+                            });
+            print 'recv_fe_interface_status>', 'no dev, returning -1'
+            self.writeResponse(msg)
+        return 1
+            
     
     def recv_fe_interface_connect(self, msg, req):
         val = unpackMsg('netif_fe_interface_connect_t', msg)
         vif = val['handle']
-        dev = self.devices.get(vif)
+        print
+        print "recv_fe_interface_connect", val
+        dev = self.getDevice(vif)
         if dev:
             dev.recv_fe_interface_connect(val, req)
         else:
             log.error('Received netif_fe_interface_connect for unknown vif: dom=%d vif=%d',
                       self.dom, vif)
-
index 5de3c2d673c2d1e8e3b0ad0c3b5f4f01c8649a8b..5f9a20f861507c03b2f0114b4135e36dc4a7dfa9 100644 (file)
@@ -70,10 +70,10 @@ typedef struct {
  */
 
 /* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
+#define CMSG_BLKIF_FE_INTERFACE_STATUS           0
 
 /* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_BLKIF_FE_DRIVER_STATUS             32
 #define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
 #define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
 #define CMSG_BLKIF_FE_INTERFACE_QUERY           35
@@ -84,25 +84,25 @@ typedef struct {
 #define blkif_sector_t u64
 
 /*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
+ * CMSG_BLKIF_FE_INTERFACE_STATUS:
  *  Notify a guest about a status change on one of its block interfaces.
  *  If the interface is DESTROYED or DOWN then the interface is disconnected:
  *   1. The shared-memory frame is available for reuse.
  *   2. Any unacknowledged messages pending on the interface were dropped.
  */
-#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define BLKIF_INTERFACE_STATUS_CLOSED       0 /* Interface doesn't exist.    */
 #define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
 #define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-#define BLKIF_INTERFACE_STATUS_CHANGED      3 /* A device has been added or removed. */
+//#define BLKIF_INTERFACE_STATUS_CHANGED      3 /* A device has been added or removed. */
 typedef struct {
     u32 handle; /*  0 */
     u32 status; /*  4 */
     u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
     domid_t domid; /* 10: status != BLKIF_INTERFACE_STATUS_DESTROYED */
-} PACKED blkif_fe_interface_status_changed_t; /* 12 bytes */
+} PACKED blkif_fe_interface_status_t; /* 12 bytes */
 
 /*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
+ * CMSG_BLKIF_FE_DRIVER_STATUS:
  *  Notify the domain controller that the front-end driver is DOWN or UP.
  *  When the driver goes DOWN then the controller will send no more
  *  status-change notifications.
@@ -121,7 +121,7 @@ typedef struct {
     /* OUT */
     /* Driver should query interfaces [0..max_handle]. */
     u32 max_handle;    /*  4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
+} PACKED blkif_fe_driver_status_t; /* 8 bytes */
 
 /*
  * CMSG_BLKIF_FE_INTERFACE_CONNECT:
@@ -172,7 +172,7 @@ typedef struct {
 #define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
 
 /* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
+#define CMSG_BLKIF_BE_DRIVER_STATUS 32
 
 /*
  * Message request/response definitions for block-device messages.
@@ -325,14 +325,14 @@ typedef struct {
 } PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
 
 /*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
+ * CMSG_BLKIF_BE_DRIVER_STATUS:
  *  Notify the domain controller that the back-end driver is DOWN or UP.
  *  If the driver goes DOWN while interfaces are still UP, the controller
  *  will automatically send DOWN notifications.
  */
 typedef struct {
     u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
+} PACKED blkif_be_driver_status_t; /* 4 bytes */
 
 
 /******************************************************************************
@@ -340,22 +340,22 @@ typedef struct {
  */
 
 /* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
+#define CMSG_NETIF_FE_INTERFACE_STATUS   0
 
 /* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
+#define CMSG_NETIF_FE_DRIVER_STATUS             32
 #define CMSG_NETIF_FE_INTERFACE_CONNECT         33
 #define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
 #define CMSG_NETIF_FE_INTERFACE_QUERY           35
 
 /*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
+ * CMSG_NETIF_FE_INTERFACE_STATUS:
  *  Notify a guest about a status change on one of its network interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
+ *  If the interface is CLOSED or DOWN then the interface is disconnected:
  *   1. The shared-memory frame is available for reuse.
  *   2. Any unacknowledged messgaes pending on the interface were dropped.
  */
-#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
+#define NETIF_INTERFACE_STATUS_CLOSED       0 /* Interface doesn't exist.    */
 #define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
 #define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
 #define NETIF_INTERFACE_STATUS_CHANGED      3 /* A device has been added or removed. */
@@ -365,17 +365,17 @@ typedef struct {
     u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
     u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
     domid_t    domid;  /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */
-} PACKED netif_fe_interface_status_changed_t; /* 18 bytes */
+} PACKED netif_fe_interface_status_t; /* 18 bytes */
 
 /*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
+ * CMSG_NETIF_FE_DRIVER_STATUS:
  *  Notify the domain controller that the front-end driver is DOWN or UP.
  *  When the driver goes DOWN then the controller will send no more
  *  status-change notifications.
  *  If the driver goes DOWN while interfaces are still UP, the domain
  *  will automatically take the interfaces DOWN.
  * 
- *  NB. The controller should not send an INTERFACE_STATUS_CHANGED message
+ *  NB. The controller should not send an INTERFACE_STATUS message
  *  for interfaces that are active when it receives an UP notification. We
  *  expect that the frontend driver will query those interfaces itself.
  */
@@ -387,7 +387,7 @@ typedef struct {
     /* OUT */
     /* Driver should query interfaces [0..max_handle]. */
     u32        max_handle;    /*  4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
+} PACKED netif_fe_driver_status_t; /* 8 bytes */
 
 /*
  * CMSG_NETIF_FE_INTERFACE_CONNECT:
@@ -437,7 +437,7 @@ typedef struct {
 #define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
 
 /* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
+#define CMSG_NETIF_BE_DRIVER_STATUS 32
 
 /*
  * Message request/response definitions for net-device messages.
@@ -533,14 +533,14 @@ typedef struct {
 } PACKED netif_be_disconnect_t; /* 12 bytes */
 
 /*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
+ * CMSG_NETIF_BE_DRIVER_STATUS:
  *  Notify the domain controller that the back-end driver is DOWN or UP.
  *  If the driver goes DOWN while interfaces are still UP, the domain
  *  will automatically send DOWN notifications.
  */
 typedef struct {
     u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
+} PACKED netif_be_driver_status_t; /* 4 bytes */
 
 
 /******************************************************************************